﻿using System;
using System.Configuration;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using Masterduner.SourceStudio.Practices.DevelopmentLibrary.Utilities.DataConfiguration.Controls;
using Config = System.Configuration.Configuration;

namespace Masterduner.SourceStudio.Practices.DevelopmentLibrary.Utilities.DataConfiguration.Windows
{
    public partial class MainWindow : Form
    {
        private FileInfo _selectedConfigFile;
        private ConfigurationLoader _configurationLoader;

        public MainWindow()
        {
            InitializeComponent();
        }

        #region MainWindow_Load
        private void MainWindow_Load(object sender, EventArgs e)
        {
            this.SetFormBackgroundColor();
            this.SetControlsContainerBackgroundColor();
            this.SetOkButtonBackgroundColor();
            this.SetCloseButtonBackgroundColor();
            this.AttachBrowseControl();
            //this.DisableOkButton();
        }
        #endregion

        #region SetFormBackgroundColor
        private void SetFormBackgroundColor()
        {
            this.BackColor = ColorTranslator.FromHtml("#16160E");
        }
        #endregion

        #region SetControlsContainerBackgroundColor
        private void SetControlsContainerBackgroundColor()
        {
            this.panControlsContainer.BackColor = ColorTranslator.FromHtml("#FFFFFF");
        }
        #endregion

        #region SetOkButtonBackgroundColor
        private void SetOkButtonBackgroundColor()
        {
            this.btnOK.BackColor = ColorTranslator.FromHtml("#028760");
        }
        #endregion

        #region SetCloseButtonBackgroundColor
        private void SetCloseButtonBackgroundColor()
        {
            this.btnClose.BackColor = ColorTranslator.FromHtml("#2B2B2B");
        }
        #endregion

        #region btnClose_Click
        private void btnClose_Click(object sender, EventArgs e)
        {
            this.Close();
        }
        #endregion

        #region AttachBrowseControl
        private void AttachBrowseControl()
        {
            BrowseButton btnBrowse = new BrowseButton();
            btnBrowse.AfterSelected += new EventHandler(btnBrowse_AfterSelected);
            this.panControlsContainer.Controls.Clear();
            this.panControlsContainer.Controls.Add(btnBrowse);
        }

        void btnBrowse_AfterSelected(object sender, EventArgs e)
        {
            this._selectedConfigFile = sender.ForceTo<BrowseButton>().SelectedConfigurationFile;
            this.panControlsContainer.Controls.Clear();
            this._configurationLoader = new ConfigurationLoader() { ConfigurationFile = this._selectedConfigFile };
            this.panControlsContainer.Controls.Add(this._configurationLoader);
        }
        #endregion

        #region DisableOkButton
        private void DisableOkButton()
        {
            this.btnOK.Enabled = false;
        }
        #endregion

        #region btnOK_Click
        private void btnOK_Click(object sender, EventArgs e)
        {
            string userConfigFileName = string.Empty;
            if (_configurationLoader.RequiredSaveToUserConfig() && _configurationLoader.ShowSaveDialog(out userConfigFileName) == DialogResult.OK)
            {
                this.RemoveAndCreateUserConfiguration(userConfigFileName);
                this.SaveIntoUserConfig(userConfigFileName);
            }
            else
            {
                this.SaveIntoAppConfig();
            }
        }
        #endregion

        #region RemoveAndCreateUserConfiguration
        private void RemoveAndCreateUserConfiguration(string fileName)
        {
            FileInfo fileInfo = new FileInfo(fileName);
            ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap() { ExeConfigFilename = this._selectedConfigFile.FullName };
            Config appConfig = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
            if (appConfig.Sections[Configuration.UserCustomizedConfigurationFilesSection.SectionName].NotIsNull())
            {
                Configuration.UserCustomizedConfigurationFilesSection section = appConfig.Sections[Configuration.UserCustomizedConfigurationFilesSection.SectionName].ForceTo<Configuration.UserCustomizedConfigurationFilesSection>();
                section.UserCustomizedConfigurationSectionGroups.Remove(Data.Configuration.DataConfigurationService.ConfigurationSectionGroupName);
                Configuration.UserCustomizedConfigurationFileElement element = new Configuration.UserCustomizedConfigurationFileElement()
                {
                    Name = Data.Configuration.DataConfigurationService.ConfigurationSectionGroupName,
                    Directory = fileInfo.Directory.FullName,
                    FileName = fileInfo.Name
                };
                section.UserCustomizedConfigurationSectionGroups.Add(element);
            }
            else
            {
                Configuration.UserCustomizedConfigurationFileElement element = new Configuration.UserCustomizedConfigurationFileElement()
                {
                    Name = Data.Configuration.DataConfigurationService.ConfigurationSectionGroupName,
                    Directory = fileInfo.Directory.FullName,
                    FileName = fileInfo.Name
                };
                Configuration.UserCustomizedConfigurationFilesSection section = new Configuration.UserCustomizedConfigurationFilesSection();
                section.UserCustomizedConfigurationSectionGroups.Add(element);
                appConfig.Sections.Add(Configuration.UserCustomizedConfigurationFilesSection.SectionName, section);
            }
            appConfig.Save(ConfigurationSaveMode.Modified, false);
        }
        #endregion

        private void SaveIntoAppConfig()
        {
            ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap() { ExeConfigFilename = this._selectedConfigFile.FullName };
            Config config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
            config.SectionGroups.Remove(Data.Configuration.DataConfigurationService.ConfigurationSectionGroupName);
            Data.Configuration.DatabaseProviderSection section1 = new Data.Configuration.DatabaseProviderSection();
            Data.Configuration.DatabaseConnectionSection section2 = new Data.Configuration.DatabaseConnectionSection();
            ConfigurationSectionGroup group = new ConfigurationSectionGroup();
            config.SectionGroups.Add(Data.Configuration.DataConfigurationService.ConfigurationSectionGroupName, group);
            group.Sections.Add(Data.Configuration.DatabaseProviderSection.SectionName, section1);
            group.Sections.Add(Data.Configuration.DatabaseConnectionSection.SectionName, section2);
            foreach (dynamic item in this._configurationLoader.GetDatabases())
            {
                section1.DatabaseProviders.Add(new Data.Configuration.DatabaseProviderElement() { Name = item.Name, Type = item.Type });
            }
            foreach (dynamic item in this._configurationLoader.GetConnections())
            {
                section2.DatabaseConnections.Add(new Data.Configuration.DatabaseConnectionElement()
                {
                    Name = item.Name,
                    ConnectionString = item.ConnectionString,
                    CommandExecuteTimeout = item.Timeout,
                    ExceptionProcessMode = item.ErrorHandleMode,
                    DatabaseProviderName = item.Provider
                });
            }
            if (this._configurationLoader.ProtectionProvider == 2 || this._configurationLoader.ProtectionProvider == 3)
            {
                string providerName = string.Empty;
                if (this._configurationLoader.ProtectionProvider == 2)
                    providerName = "RSAProtectedConfigurationProvider";
                else
                    providerName = "DPAPIProtectedConfigurationProvider";
                section1.SectionInformation.ProtectSection(providerName);
                section1.SectionInformation.ForceSave = true;
                section2.SectionInformation.ProtectSection(providerName);
                section2.SectionInformation.ForceSave = true;
            }
            try
            {
                config.Save(ConfigurationSaveMode.Modified);
                this.Close();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        #region SaveIntoUserConfig
        private void SaveIntoUserConfig(string fileName)
        {
            FileInfo fileInfo = new FileInfo(fileName);
            if (fileInfo.Exists) fileInfo.Delete();
            ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap() { ExeConfigFilename = fileInfo.FullName };
            Config config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
            Data.Configuration.DatabaseProviderSection section1 = new Data.Configuration.DatabaseProviderSection();
            Data.Configuration.DatabaseConnectionSection section2 = new Data.Configuration.DatabaseConnectionSection();
            ConfigurationSectionGroup group = new ConfigurationSectionGroup();
            config.SectionGroups.Add(Data.Configuration.DataConfigurationService.ConfigurationSectionGroupName, group);
            group.Sections.Add(Data.Configuration.DatabaseProviderSection.SectionName, section1);
            group.Sections.Add(Data.Configuration.DatabaseConnectionSection.SectionName, section2);
            foreach (dynamic item in this._configurationLoader.GetDatabases())
            {
                section1.DatabaseProviders.Add(new Data.Configuration.DatabaseProviderElement() { Name = item.Name, Type = item.Type });
            }
            foreach (dynamic item in this._configurationLoader.GetConnections())
            {
                section2.DatabaseConnections.Add(new Data.Configuration.DatabaseConnectionElement()
                {
                    Name = item.Name,
                    ConnectionString = item.ConnectionString,
                    CommandExecuteTimeout = item.Timeout,
                    ExceptionProcessMode = item.ErrorHandleMode,
                    DatabaseProviderName = item.Provider
                });
            }
            if (this._configurationLoader.ProtectionProvider == 2 || this._configurationLoader.ProtectionProvider == 3)
            {
                string providerName = string.Empty;
                if (this._configurationLoader.ProtectionProvider == 2)
                    providerName = "RSAProtectedConfigurationProvider";
                else
                    providerName = "DPAPIProtectedConfigurationProvider";
                section1.SectionInformation.ProtectSection(providerName);
                section1.SectionInformation.ForceSave = true;
                section2.SectionInformation.ProtectSection(providerName);
                section2.SectionInformation.ForceSave = true;
            }
            try
            {
                config.Save(ConfigurationSaveMode.Modified);
                this.Close();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        #endregion
    }
}
